package config

import (
	"errors"
	"fmt"
	"github.com/chmodke/gitmm/log"
	"path/filepath"
	"strings"
	"text/template"
)

// Config 配置对象
type Config struct {
	Remotes []Remote
	Repos   []Repo
}

// Remote 远程配置对象
type Remote struct {
	Name   string //远程名称
	Domain string //远程域名
	Tpl    string //仓库路全路径模板
}

// Repo 仓库配置对象
type Repo struct {
	Name   string //仓库名称
	Path   string //仓库子路径
	Local  string //仓库本地存储位置
	Branch string //默认分支
	Remote string //默认远程名称
}

const DEFAULT_REPO_TPL = `{{.Remote.Domain}}{{.Repo.Path}}`

// GetRemoteNames 获取所有的远程名称
func (config *Config) GetRemoteNames() []string {
	var names []string
	for _, remote := range config.Remotes {
		names = append(names, remote.Name)
	}
	return names
}

// DefineRemote 指定名称的远程是否配置
func (config *Config) DefineRemote(name string) bool {
	for _, remote := range config.Remotes {
		if name == remote.Name {
			return true
		}
	}
	return false
}

// GetRemote 获取指定名称的远程配置
func (config *Config) GetRemote(name string) (Remote, error) {
	for _, remote := range config.Remotes {
		if name == remote.Name {
			return remote, nil
		}
	}
	return Remote{}, errors.New("not found remote " + name)
}

// GetRepoNames 获取所有仓库名称
func (config *Config) GetRepoNames() []string {
	var names []string
	for _, repo := range config.Repos {
		names = append(names, repo.Name)
	}
	return names
}

// GetRepoLocalPaths 获取所有仓库配置的本地路径
func (config *Config) GetRepoLocalPaths() []string {
	var paths []string
	for _, repo := range config.Repos {
		paths = append(paths, repo.Local)
	}
	return paths
}

// GetRepo 获取指定名称的仓库配置
func (config *Config) GetRepo(name string) (Repo, error) {
	for _, repo := range config.Repos {
		if name == repo.Name {
			return repo, nil
		}
	}
	return Repo{}, errors.New("not found repo " + name)
}

func (remote Remote) String() string {
	return fmt.Sprintf("[%s]%s", remote.Name, remote.Domain)
}

func (repo Repo) String() string {
	return fmt.Sprintf("[%s]%s", repo.Name, repo.Path)
}

func (repo *Repo) RemotePath(remote Remote) string {
	if len(remote.Tpl) == 0 {
		return fmt.Sprintf("%s%s", remote.Domain, repo.Path)
	}
	return renderPath(repo, remote)
}

// LocalPath 获取仓库在那，.git所在位置
func (repo *Repo) LocalPath(workDir string) string {
	return filepath.Join(workDir, repo.Local)
}

func renderPath(repo *Repo, remote Remote) string {
	var tmpl *template.Template
	var err error
	if len(remote.Tpl) == 0 {
		tmpl, err = template.New("repoTemplate").Parse(DEFAULT_REPO_TPL)
	} else {
		tmpl, err = template.New("repoTemplate").Parse(remote.Tpl)
	}
	if err != nil {
		return ""
	}
	context := struct {
		Repo   Repo
		Remote Remote
	}{
		Repo:   *repo,
		Remote: remote,
	}
	var builder strings.Builder
	err = tmpl.Execute(&builder, context)
	if err != nil {
		log.Println(err.Error())
		return ""
	}
	return builder.String()
}
